﻿using System;
using System.Data;
using System.Windows.Forms;
using System.Xml;
using Home.Haushalt.Lib;
using Infragistics.Win;
using Infragistics.Win.UltraWinGrid;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using Home.Haushalt.Lib.Element;
using System.Diagnostics;
using System.ComponentModel;

namespace Home.Haushalt.Gui
{
    /// <summary>
    /// 
    /// </summary>
    public partial class FrmMain : FrmGridForm
    {
        private string _preSelectedUserName = "";
        private BackgroundWorker bwLoadElementData = new BackgroundWorker();

        /// <summary>
        /// 
        /// </summary>
        public FrmMain()
        {
            //Import(@"L:\DATEN\Programme\Haushalt - Kopie\Data");

            InitializeComponent();

            bwLoadElementData.DoWork += new DoWorkEventHandler(LoadDecryptDataTables_DoWork);
            bwLoadElementData.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bwLoadElementData.WorkerSupportsCancellation = true;

            this.StartPosition = FormStartPosition.CenterScreen;
        }

        #region DATA IMPORT

        ///// <summary>
        ///// 
        ///// </summary>
        //private void Import(string sourcePath)
        //{
        //    //Import
        //    string targetPath = sourcePath + @"\result";
        //    if (!Directory.Exists(targetPath))
        //        Directory.CreateDirectory(targetPath);
        //    string fileContent = "";
        //    string targetFilename = "";
        //    Type elementType = null;

        //    //Posten
        //    elementType = Posten.ElementType;

        //    fileContent = GetFileContent(sourcePath, elementType.Name + ".xml");
        //    fileContent = fileContent.Replace("xsi:", "");
        //    fileContent = fileContent.Replace("i=\"", "t=\"");
        //    fileContent = fileContent.Replace("q=\"", "i=\"");
        //    fileContent = fileContent.Replace("t=\"31.12.9999\" ", "");

        //    targetFilename = WriteFile(targetPath, elementType.Name + ".xml", fileContent);

        //    Import(targetFilename, elementType);

        //    //Date
        //    elementType = Date.ElementType;
        //    targetFilename = targetPath + "\\" + elementType.Name + ".xml";
        //    if (File.Exists(targetFilename))
        //        File.Delete(targetFilename);

        //    StreamWriter sw = new StreamWriter(targetFilename, true, System.Text.Encoding.UTF8);

        //    sw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
        //        "<CDateCollection xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ItemObjects>");
        //    int id = 0;
        //    foreach (string filename in Directory.GetFiles(sourcePath, "date*.xml"))
        //    {
        //        using (StreamReader sr = new StreamReader(filename))
        //        {
        //            while (!sr.EndOfStream)
        //            {
        //                string line = sr.ReadLine().Trim();
        //                if (line.StartsWith("<anyType"))
        //                {
        //                    sw.WriteLine(line.Replace("xsi:", "i=\"" + (id++) + "\" "));
        //                }
        //            }
        //            sr.Close();
        //        }
        //    }
        //    sw.WriteLine("</ItemObjects></CDateCollection>");

        //    sw.Close();

        //    Import(targetFilename, elementType);

        //    //Document
        //    elementType = Document.ElementType;

        //    fileContent = GetFileContent(sourcePath, elementType.Name + ".xml");
        //    fileContent = fileContent.Replace("xsi:", "c=\"false\" ");

        //    targetFilename = WriteFile(targetPath, elementType.Name + ".xml", fileContent);

        //    Import(targetFilename, elementType);

        //    //Page
        //    elementType = Page.ElementType;

        //    fileContent = GetFileContent(sourcePath, elementType.Name + ".xml");
        //    fileContent = fileContent.Replace("xsi:", "");
        //    fileContent = fileContent.Replace("m=\"\" ", "");
        //    fileContent = fileContent.Replace("k=\"\" ", "");
        //    fileContent = fileContent.Replace("c=\"false\" ", "");
        //    fileContent = fileContent.Replace("c=\"true\" ", "");

        //    targetFilename = WriteFile(targetPath, elementType.Name + ".xml", fileContent);

        //    Import(targetFilename, elementType);


        //    //Opponent
        //    elementType = Opponent.ElementType;

        //    fileContent = GetFileContent(sourcePath, elementType.Name + ".xml");
        //    fileContent = fileContent.Replace("xsi:", "");

        //    targetFilename = WriteFile(targetPath, elementType.Name + ".xml", fileContent);

        //    Import(targetFilename, elementType);


        //    //Member
        //    elementType = Member.ElementType;
        //    targetFilename = targetPath + "\\" + elementType.Name.ToLower() + ".xml";

        //    if (File.Exists(targetFilename))
        //        File.Delete(targetFilename);

        // ------------->>   HCryptography cry = new HCryptography("HIER KENNWORT EINGEBEN");
        //    File.Copy(sourcePath + "\\" + elementType.Name + ".xml", targetFilename);

        //    cry.FileDecrypt(targetFilename);

        //    fileContent = GetFileContent(targetPath, elementType.Name + ".xml");
        //    fileContent = fileContent.Replace("xsi:", "");

        //    targetFilename = WriteFile(targetPath, elementType.Name + ".xml", fileContent);

        //    Import(targetFilename, elementType);
        //    HCryptography cry2 = new HCryptography("000000");
        //    cry2.FileEncrypt(targetFilename);

        //    MessageBox.Show("Import Fertig");
        //}
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="sourcePath"></param>
        ///// <param name="fileName"></param>
        ///// <returns></returns>
        //private string GetFileContent(string sourcePath, string fileName)
        //{
        //    string sourceFilename = sourcePath + "\\" + fileName;
        //    using (StreamReader sr = new StreamReader(sourceFilename))
        //    {
        //        string fileContent = sr.ReadToEnd();
        //        sr.Close();
        //        return fileContent;
        //    }
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="targetPath"></param>
        /// <param name="fileName"></param>
        /// <param name="fileContent"></param>
        /// <returns></returns>
        private string WriteFile(string targetPath, string fileName, string fileContent)
        {
            string targetFilename = targetPath + "\\" + fileName.ToLower();
            StreamWriter sw = new StreamWriter(targetFilename, false, System.Text.Encoding.UTF8);
            sw.Write(fileContent);
            sw.Close();

            return targetFilename;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="elementType"></param>
        private void Import(string filename, Type elementType)
        {
            using (DataSet ds = new DataSet())
            {
                ds.OpenSchema(elementType);
                DataTable tt = ds.Tables[0];

                XmlDocument sourceDoc = new XmlDocument();
                sourceDoc.Load(filename);
                foreach (XmlNode sourceNode in sourceDoc.GetElementsByTagName("anyType"))
                {
                    DataRow row = tt.NewRow();
                    tt.Rows.Add(row);

                    foreach (XmlAttribute attr in sourceNode.Attributes)
                    {
                        if (tt.Columns.Contains(attr.Name))
                        {
                            if (tt.Columns[attr.Name].DataType.Name == "DateTime")
                            {
                                row[attr.Name] = attr.Value.ToDateTime();
                            }
                            else
                            {
                                row[attr.Name] = attr.Value;
                            }
                        }
                    }
                }
                ds.WriteXml(filename);
            }
        }

        #endregion IMPORTING

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmLogin_Load(object sender, EventArgs e)
        {
            statusProcessBar.Visible = false;
            txtFullTextSearch.Visible = false;

            SetStatusImage();

            //Benutzer-Auswahl initialisieren und anzeigen
            ucUserSelector.OnSelected += new EventHandler(ucUserSelector_OnSelected);
            ucUserSelector.DataBind(DAO.Settings);

            txtPass.KeyUp += new KeyEventHandler(txtPass_KeyUp);

            ShowLogin(DAO.Credential.PassAssigned ? LoginModes.Normal : LoginModes.Initial, DAO.Settings.Selected.UserName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ucUserSelector_OnSelected(object sender, EventArgs e)
        {
            lblPass.Text = LO.Common("lblPass", DAO.Settings.Selected.UserName);

            if (!_preSelectedUserName.Equals(DAO.Settings.Selected.UserName))
            {
                _preSelectedUserName = DAO.Settings.Selected.UserName;

                if (bwLoadElementData.IsBusy)
                {
                    bwLoadElementData.CancelAsync();
                }

                //Reset der Daten vom aktuellen Benutzer
                //Die Stelle und idie Reihenfolge sind wichtig (sonst werden Tabellen der falschen Benutzer überschrieben)!
                WindowController.Reset();
                DAO.Reset();
                LayoutController.Reset();

                bwLoadElementData.RunWorkerAsync();
            }

            //Für Debugging
            if (!Program.StartArgs[Program.STARTARG_PASSWORD].Equals(string.Empty))
            {
                while (bwLoadElementData.IsBusy) { Application.DoEvents(); }

                DAO.UserLogins.Add(DAO.Settings.Selected.UserName, Program.StartArgs[Program.STARTARG_PASSWORD]);

                Program.StartArgs[Program.STARTARG_PASSWORD] = string.Empty;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoadDecryptDataTables_DoWork(object sender, DoWorkEventArgs e)
        {
            DAO.LoadDecryptDataTables();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            LoadFavoriteButtons();
        }



        #region LOGIN SUPPORT

        /// <summary></summary>
        private LoginModes _loginMode = LoginModes.Initial;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnShowChangePass_Click(object sender, EventArgs e)
        {
            ShowLogin(LoginModes.Change, DAO.Settings.Selected.UserName);
        }

        /// <summary>
        /// 
        /// </summary>
        private void LoadFavoriteButtons()
        {
            //Favorite-Button erstellen
            pnlFavorite.Controls.Clear();
            pnlFavorite.Controls.Add(btnLogin);

            foreach (DataRow row in DAO.Tables[GridLayout.ElementType].Select(string.Format("{0} = true", GridLayout.Fields.StartFavorite)))
            {
                HButton btn = new HButton();
                btn.Click += new EventHandler(btnLogin_Click);
                btn.Text = row[GridLayout.Fields.Name].ToString();
                btn.Tag = row;
                btn.Width = btnLogin.Width;
                pnlFavorite.Controls.Add(btn);
            }

            pnlFavorite.Width = 0;
            foreach (Control ctrl in pnlFavorite.Controls)
            {
                pnlFavorite.Width += ctrl.Width + ctrl.Margin.Left + ctrl.Margin.Right;
            }
            pnlFavorite.Width += pnlFavorite.Margin.Left + pnlFavorite.Margin.Right;

            Control parentControl = pnlFavorite.Parent;
            pnlFavorite.Left = (parentControl.Width / 2) - (pnlFavorite.Width / 2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtPass_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                btnLogin_Click(btnLogin, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="loginMode"></param>
        /// <param name="userName"></param>
        internal void ShowLogin(LoginModes loginMode, string userName)
        {
            //Login initialisieren
            _loginMode = loginMode;

            this.toolStrip.Enabled = false;

            if (_ucGridControl != null)
            {
                this.Controls.Remove(_ucGridControl);
                _ucGridControl.Dispose();
            }

            pnlLogin.Dock = DockStyle.Fill;
            pnlLogin.Visible = true;
            txtPass.Text = txtPass2.Text = "";

            ucUserSelector.SetUser(userName);

            this.Text = "Haushalt";

            switch (loginMode)
            {
                case LoginModes.Initial:

                    SetStatusText("FirstLogin");
                    ucUserSelector.Top = 20;
                    lblPass.Text = "Wiederholen";
                    lblPassNote.Visible = true;
                    lblPassNote.Text = "Sie melden sich das Erstemal. Geben Sie ein Kennwort ein:";
                    lblPass2.Visible = txtPass2.Visible = true;
                    lblOldPass.Visible = txtOldPass.Visible = false;
                    btnShowChangePass.Visible = false;
                    break;

                case LoginModes.Normal:
                    SetStatusText("Login");
                    ucUserSelector.Top = 120;
                    lblPass.Text = LO.Common("lblPass", DAO.Settings.Selected.UserName);
                    lblPass.Focus();
                    lblPassNote.Visible = false;
                    lblPass2.Visible = txtPass2.Visible = false;
                    lblOldPass.Visible = txtOldPass.Visible = false;
                    btnShowChangePass.Visible = true;
                    break;

                case LoginModes.Change:

                    SetStatusText("ChangePass");
                    ucUserSelector.Top = 20;
                    lblPass.Text = "Wiederholen";
                    lblPassNote.Visible = true;
                    lblPassNote.Text = "Geben Sie neues Kennwort ein:";
                    lblPass2.Visible = txtPass2.Visible = true;
                    lblOldPass.Visible = txtOldPass.Visible = true;
                    lblOldPass.Focus();
                    btnShowChangePass.Visible = false;
                    break;
            }

            Application.DoEvents();
            if (DAO.UserLogins.ContainsKey(userName))
            {
                _loginMode = LoginModes.Normal;
                txtPass.Text = DAO.UserLogins[userName];

                btnLogin_Click(btnLogin, null);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLogin_Click(object sender, EventArgs e)
        {
            bool logged = false;
            HCryptography currentKeyCry = new HCryptography(txtPass.Text);

            switch (_loginMode)
            {
                case LoginModes.Normal:

                    logged = DAO.Login(txtPass.Text);

                    if (!logged)
                    {
                        MessageBox.Show("Kennwort ist falsch! Versuchen Sie es noch einmal!");
                        SetStatusText("LoginError");
                    }

                    break;

                case LoginModes.Initial:

                    logged = DAO.Credential.Update(txtPass.Text);


                    if (!logged)
                    {
                        MessageBox.Show("Ups. Ein Fehler bei Neuverschlüsselung");
                        SetStatusText("Error");
                        return;
                    }

                    break;

                case LoginModes.Change:

                    logged = DAO.Login(txtOldPass.Text);

                    if (!logged)
                    {
                        MessageBox.Show("Aktuelles Kennwort ist falsch! Versuchen Sie es noch einmal!");
                        SetStatusText("LoginError");
                        return;
                    }

                    if (!txtPass.Text.Equals(txtPass2.Text))
                    {
                        MessageBox.Show("Neues Kennwort stimmt mit der Wiederholung nicht überein!");
                        SetStatusText("UserInputError");
                        return;
                    }

                    logged = DAO.Credential.Update(txtPass.Text);

                    if (logged)
                    {
                        DAO.Settings.SaveSettings();
                    }
                    else
                    {
                        MessageBox.Show("Ups. Ein Fehler bei Neuverschlüsselung");
                        SetStatusText("Error");
                        return;
                    }

                    break;
            }

            if (logged)
            {
                if (!DAO.UserLogins.ContainsKey(DAO.Settings.Selected.UserName))
                {
                    DAO.UserLogins.Add(DAO.Settings.Selected.UserName, txtPass.Text);
                }

                pnlLogin.Enabled = false;

                DAO.LoadMissingDataTables();
                
                SetStatusText("DataLoading");

                InitMainForm();

                Application.DoEvents();

                this.toolStrip.Enabled = true;
                pnlLogin.Visible = false;
                pnlLogin.Enabled = true;

                SetStatusText("Ready");

                HButton btn = (HButton)sender;
                if (btn.Tag != null)
                {
                    DataRow row = (DataRow)btn.Tag;

                    FrmGridForm frmGridForm = new FrmGridForm(UcGridForm.Instatiate(ElementBase.GetType(row[GridLayout.Fields.Table].ToString()), DefaultColumnSets.GridDefault, row[GridLayout.Fields.Name].ToString()));
                    frmGridForm.Show();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (_loginMode == LoginModes.Change)
            {
                ShowLogin(LoginModes.Normal, DAO.Settings.Selected.UserName);
            }
            else
            {
                Close();
            }
        }

        #endregion LOGIN SUPPORT

        /// <summary>
        /// 
        /// </summary>
        private void InitMainForm()
        {
            _ucGridControl = new UcGridFormMain();
            this.Controls.Add(_ucGridControl);

            this.Init();

            this.Text = LO.Common("MainFormCaption", DAO.Settings.Selected.UserName);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmLogin_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Geänderte Daten speichern, Temp-Dateien löschen
            DAO.Reset();

            //Zwieschenablage löschen
            Clipboard.Clear();
        }

    }
}
